package cn.wolfcode.luowowo.search.service.impl;

import cn.wolfcode.luowowo.search.domain.StrategyTemplate;
import cn.wolfcode.luowowo.search.query.StrategySearchQuery;
import cn.wolfcode.luowowo.search.repository.StrategySearchRepository;
import cn.wolfcode.luowowo.search.service.IStrategySearchService;
import cn.wolfcode.luowowo.search.vo.StatisVO;
import com.alibaba.dubbo.config.annotation.Service;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.bucket.composite.CompositeAggregation;
import org.elasticsearch.search.aggregations.bucket.composite.CompositeAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.composite.CompositeValuesSourceBuilder;
import org.elasticsearch.search.aggregations.bucket.composite.TermsValuesSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import java.util.*;

@Service
public class StrategySearchServiceImpl implements IStrategySearchService {

    @Autowired
    private StrategySearchRepository repository;

    @Autowired
    private ElasticsearchTemplate template;

    public void save(StrategyTemplate template) {
        repository.save(template);
    }

    public List<StatisVO> queryGroup(String idField, String nameField, String groupName) {
        List<CompositeValuesSourceBuilder<?>> sources = new ArrayList<>();

        CompositeValuesSourceBuilder idSource = new TermsValuesSourceBuilder("id");
        idSource.field(idField);
        CompositeValuesSourceBuilder nameSource = new TermsValuesSourceBuilder("name");
        nameSource.field(nameField);

        sources.add(idSource);
        sources.add(nameSource);

        CompositeAggregationBuilder aggBuilder = new CompositeAggregationBuilder(groupName, sources);

        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.addAggregation(aggBuilder);
        builder.withPageable(PageRequest.of(0, 1));

        AggregatedPage<StrategyTemplate> page = (AggregatedPage<StrategyTemplate>) repository.search(builder.build());

        CompositeAggregation themeGroup = page.getAggregations().get(groupName);

        List<? extends CompositeAggregation.Bucket> buckets = themeGroup.getBuckets();

        List<StatisVO> list = new ArrayList<>();
        for (CompositeAggregation.Bucket bucket : buckets) {
            Long id = Long.valueOf(bucket.getKey().get("id").toString());
            String name = bucket.getKey().get("name").toString();
            Long count = bucket.getDocCount();

            list.add(new StatisVO(id, name, count));
        }

        //根据攻略的个数排行
        Collections.sort(list, new Comparator<StatisVO>() {
            public int compare(StatisVO o1, StatisVO o2) {
                Long ret = o2.getCount() - o1.getCount();
                return ret.intValue();
            }
        });

        return list;
    }

    public List<Map<String, Object>> queryThemeCommend() {
        List<Map<String, Object>> data = new ArrayList<>();

        List<StatisVO> themes = this.queryGroup("themeId", "themeName", "themeGroup");

        // 取前十个
        if (themes.size() > 10) {
            themes = themes.subList(0, 10);
        }

        Map<String, Object> map = null;

        for (StatisVO theme : themes) {
            map = new HashMap<>();
            List<StatisVO> dests = this.getDestByThemeId(theme.getId());
            // 关联主题
            map.put("theme", theme);
            // 关联目的地集合
            map.put("dests", dests);
            data.add(map);
        }


        return data;
    }

    private List<StatisVO> getDestByThemeId(Long themeId) {

        List<StatisVO> dests = new ArrayList<>();

        List<StrategyTemplate> list = repository.findByThemeId(themeId);

        // 实现去重功能, 使用一个list存放已存在的名称
        List<String> names = new ArrayList<>();
        for (StrategyTemplate strategyTemplate : list) {
            if (!names.contains(strategyTemplate.getDestName())) {
                dests.add(new StatisVO(strategyTemplate.getDestId(), strategyTemplate.getDestName()));
                names.add(strategyTemplate.getDestName());
            }
        }
        return dests;
    }

    public List<StatisVO> queryConditionThemes() {
        return this.queryGroup("themeId", "themeName", "themeGroup");
    }

    public List<StatisVO> queryConditionProvinces() {
        return this.queryGroup("provinceId", "provinceName", "provinceGroup");
    }

    public List<StatisVO> queryConditionCountries() {
        return this.queryGroup("countryId", "countryName", "countryGroup");
    }

    public Page query(StrategySearchQuery qo) {
        if (qo.getType() == StrategySearchQuery.CONDITION_TYPE_CHINA) {
            //国内
            return repository.search(QueryBuilders.termQuery("provinceId", qo.getTypeValue()), qo.getPageable());
        } else if (qo.getType() == StrategySearchQuery.CONDITION_TYPE_ABROAD) {
            //国外
            return repository.search(QueryBuilders.termQuery("countryId", qo.getTypeValue()), qo.getPageable());
        } else if (qo.getType() == StrategySearchQuery.CONDITION_TYPE_THEME) {
            //主题
            return repository.search(QueryBuilders.termQuery("themeId", qo.getTypeValue()), qo.getPageable());
        }

        Page<StrategyTemplate> page = repository.findAll(qo.getPageable());
        return page;
    }

    public List<StrategyTemplate> findByDestName(String destName) {
        return repository.findByDestName(destName);
    }
}
